热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

首部|门限_计算机网络测试人关于TCP的学习和梳理

篇首语:本文由编程笔记#小编为大家整理,主要介绍了计算机网络测试人关于TCP的学习和梳理相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了计算机网络测试人关于TCP的学习和梳理相关的知识,希望对你有一定的参考价值。




通过阅读《计算机网络–自顶向下方法》,以及结合最近面试的一些经历,作此笔记进行梳理和总结,也为日后的回顾作基底。



文章目录


  • 1)什么是TCP?
    • 1.1 TCP与运输层
      • *面试常问之TCP和HTTP的联系和区别

    • 1.2 TCP与UDP
      • 无连接运输:UDP
      • 面向连接的运输:TCP
      • UDP与TCP的区别:


  • 2)面试常问之TCP如何实现可靠传输?
    • 2.1 连接管理
      • 连接建立过程(三次握手):
        • *面试常问之为什么是三次握手而不是两次?

      • 连接关闭过程(四次挥手):
        • *面试常问之为什么是四次挥手而不是三次?
        • *面试常问之2MSL:


    • 2.2 校验和
    • 2.3 序列号和ACK信号
    • 2.4 超时重传
    • 2.5 滑动窗口
    • 2.6 流量控制
    • 2.7 拥塞控制





1)什么是TCP?

1.1 TCP与运输层



运输层(Transport Layer)位于应用层和网络层之间,该层协议为运行在不同主机上的应用进程之间提供了逻辑通信功能。


  • 即应用进程使用运输层提供的逻辑通信功能彼此发送报文,而无须考虑承载这些报文的物理基础设施的细节。
  • 运输层和网络层的关系:运输层位于网络层之上,网络层提供主机之间的逻辑通信服务,运输层为运行在不同主机上的进程之间提供逻辑通信服务。
  • 关于网络层级架构具体介绍可移步《【计算机网络】OSI与TCP/IP网络架构》。

运输层协议在端系统中实现:


  • 在发送端:将来自发送应用进程的应用报文分块,每块加上一个运输层首部以生成运输层报文段(segment),然后传递给网络层。
  • 在接收端:处理接收到的报文段,将其中的数据供接收应用进程使用。


*面试常问之TCP和HTTP的联系和区别


联系:


  • HTTP协议的数据一般是基于TCP协议进行传输的。
    • 关于HTTP的详细介绍可移步《【计算机网络】测试人关于HTTP的学习和梳理》。

区别:


  • HTTP属于应用层协议,定义了传输数据内容的规范。

  • TCP属于运输层协议,定义了数据传输和连接方式的规范。

  • HTTP算是短连接,TCP算是长连接。


因特网有两种协议(TCP和UDP),可为调用的应用程序提供一组不同的传输层服务。


  • UDP(用户数据报协):为调用它的应用程序提供了一种不可靠的、无连接的服务。
  • TCP(传输控制协议):为调用它的应用程序提供了一种可靠的、面向连接的服务。

TCP和UDP最基本的责任是将两个端系统间IP的交付服务扩展成运行在端系统上的两个进程之间的交付服务,即运输层的多路复用和多路分解:


  • 多路分解:将运输层报文段中的数据交付到正确的套接字。
  • 多路复用:从不同套接字中收集数据块、为其封装首部信息以生成报文段、将报文段传递给网络层。
    • 要求:套接字有唯一标识符(源端口号字段)、报文段有特殊字段指示目的套接字(目的端口号字段)。
      • 端口号(0 - 65535)
      • 周知端口号(0 - 1023),在[RFC1700]给出,在[RFC3232]更新。


网络层协议(IP,网际协议)为主机之间提供逻辑通信,其服务模型是尽力而为交付服务(best-effort delivery
service)。


  • 因为其不确保报文段的交付,不保证报文段的按序交付,不保证报文段中的数据的完整性,因此也被称为不可靠服务(unreliable service)




1.2 TCP与UDP


  • 无连接运输:UDP


    • 工作原理:给从应用进程得到的数据添加源和目的端口号字段,以及两个其他的小字段(长度和校验和),然后交给网络层,反之则将IP报文段的数据根据目的端口号交付给正确的应用进程。
    • 适用场景:
      • 实时应用(通常要求最小的发送速率,不过分延迟,可容忍部分数据丢失)
      • 特定服务(无连接因此可支持更多的活跃客户,以及更快)
      • 如DNS、SNMP、网络电话、实时视频会议、流式存储音频与视频

  • 面向连接的运输:TCP


    • 工作原理:
      • 面向连接:通过三次握手建立连接,四次挥手断开连接。
      • 通过差错检测、重传、累积确认、定时器、序号和确认号来保证可靠传输。
      • TCP定义在RFC793、RFC1122、RFC1323、RFC2018、RFC2581中。
    • 常用场景:如SMTP、Telnet等。

  • UDP与TCP的区别:


    • 无连接与有连接
    • TCP要求系统资源较多,UDP较少
    • UDP程序结构较简单
    • TCP保证数据正确性,UDP可能丢包
    • TCP保证数据顺序,UDP不保证
    • 详细的区别可参考:https://blog.csdn.net/Li_Ning_/article/details/52117463





2)面试常问之TCP如何实现可靠传输?

TCP服务模型是一个字节流,TCP必须检测并修补所有在IP层(及下面的层)产生的数据传输问题,如丢包、重复以及错误。



2.1 连接管理

一个TCP连接通常分为3个阶段:启动、数据传输、退出(关闭)。



  • 一个TCP连接由一对端点或套接字构成,通信的每一端都由一对(IP地址、端口号)所唯一标识。


  • 连接建立过程(三次握手):

    三次握手的目的不仅在于让通信双方了解一个连接正在建立,而且还利用SYN报文段交换彼此的初始序列号(ISN)。

    1. 客户端发送一个SYN报文段,并指明自己想要连接的端口号和初始序列号x(表明传送数据时的第一个数据字节的序号是 x)。
    2. 服务器发送响应SYN报文段,包含其初始序列号y,此外确认号ack=x+1(若出现丢失的情况,该SYN段会被重传)。
    3. 客户端为了确认服务器的SYN,发送确认号ack=y+1的报文。


*面试常问之为什么是三次握手而不是两次?


为了防止已失效的连接请求报文段突然又传送到了,因而产生错误。


  • 详细原因:如果在发送过程中的话,假如是两次:
    • 当A给B发送一个连接请求,因为网络的原因该请求没有按时到达,A就会重新发送一次请求,这次请求正常到,然后B就会给A一个确认请求,此时就可以传送数据了。
    • 但是当A第一次发送的数据又来到了(A以为这个包已经丢失了),那么B就会再次向A发送一个确认,此时的A就不知道这个确认的意义了,而B就会在一直等待着A给他发送信息(如果这样的次数很多就会导致资源浪费)。
    • 所以不能是两次。




  • 连接关闭过程(四次挥手):

    通过发送一个FIN报文段来发起关闭操作,由于TCP的通信模型是双向的,所以只有连接双方都完成关闭操作后,才构成一个完整关闭。

    1. 连接的主动关闭者发送一个FIN段,进入FIN_WAIT_1。
    2. 被动关闭者发送的报文段中确认号ack=u+1,以表明其已经成功收到主动关闭者的FIN。此时,上层应用程序会被告知连接的另一端已经提出了关闭的请求。
    3. 若此时没有要发送的数据时,应用程序会发起自己的关闭操作,接着被动关闭者的身份转变为主动关闭者,并发送自己的FIN。
    4. 收到连接释放报文段后,为了完成连接的关闭,还会发送一个ACK用于确认上一个FIN。注意,当出现FIN丢失的情况,发送方会重新传输直到收到一个ACK确认。


*面试常问之为什么是四次挥手而不是三次?


因为TCP连接是全双工的,也就是说接收到FIN只是说没有数据再发过来,但是还是可以向对方发送数据的,也就是说接受到一个FIN只是关闭了一个方向的数据传输,另一个方向还可以继续发送数据


  • 前两次挥手只是确认关闭了一个方向的数据,加上后面两次挥手才真正的关闭了整个全双工连接。

  • 当socket在ESTABISHED状态时,它想主动关闭连接于是向对方发送FIN请求,发送完FIN请求后它处于FIN_WAIT_1状态,当对方确认ACK报文后则处于FIN_WAIT_2状态。


    • FIN_WAIT_2表示半连接,也就是有一方要求关闭连接,另一方收到请求但是告诉它我还有一些数据要发送稍后会关闭。
    • TIME_WAIT状态表示收到对方的FIN并发送出ACK


如果是三次挥手,则可能在关闭后还有一个方向没有关




*面试常问之2MSL:


客户端接收到服务器端的 FIN 报文后进入TIME_WAIT状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:


  • 确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。
  • 等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文




2.2 校验和

发送的数据包的二进制相加然后取反,目的是检测数据在传输过程中的任何变化。


  • 如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段。

2.3 序列号和ACK信号

发送方按照顺序给要发送的数据包的每个字节都标上编号。
接收方接收到发送方的数据包之后,回传一个ACK信号,标识下一个需求的数据包初始字节编号。


  • 序列号:
    • TCP提供一个字节流接口,把一个应用程序的字节流转换为一组IP可以携带的分组,这些分组包含序列号。
    • 序列号在TCP中实际代表了每个分组的第一个字节在整个数据流中的字节偏移。
    • 通过序列号的使用,一个TCP接收端可丢弃重复的报文段和记录以乱序到达的报文段。

  • ACK信号:
    • 当TCP接收到另一端的数据时,会发送一个确认。
    • TCP使用的ACK是累积的,一个指示字节号N的ACK表示了所有直到N的字节(但不包括N)已经成功被接收了。



2.4 超时重传



发送方没有接收到响应的ACK报文原因可能有两点:


  • 数据在传输过程中由于网络原因等直接全体丢包,接收方没有接收到。
  • 接收方接收到了响应的数据,但是发送的ACK报文响应却由于网络原因丢包了。


TCP在解决这个问题的时候引入了一个新的机制,叫做超时重传机制。


发送方在发送完数据后等待一个时间,该时间内没有接收到ACK报文,那么就会重新发送刚才的数据。


  • 如果是上述第一个原因,则接收方收到二次重发的数据后,便进行ACK应答。
  • 如果是第二个原因,接收方发现接收的数据已存在(判断存在的根据就是序列号,所以说序列号还有去除重复数据的作用),那么直接丢弃,仍旧发送ACK应答。
  • 等待时间的设定:
    • 为了保证在任何环境下都有一个高性能的通信,因此这个最大超时时间(也就是等待的时间)是动态计算的。
      • 超时以500ms(0.5秒)为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。
      • 重发一次后,仍未响应,那么等待2500ms的时间后,再次重传。等待4500ms的时间继续重传。以一个指数的形式增长。
    • 累计到一定的重传次数,TCP就认为网络或者对端出现异常,强制关闭连接。



2.5 滑动窗口



TCP必需要解决的可靠传输以及包乱序(reordering)的问题,所以,TCP必需要知道网络实际的数据处理带宽或是数据处理速度,这样才不会引起网络拥塞,导致丢包。


  • 发送方滑动窗口示意图:

    分成了四个部分,分别是(其中那个黑模型就是滑动窗口):


    1. 已收到ack确认的数据。
    2. 已发出但还没收到ack的。
    3. 在窗口中还没有发出的(接收方还有空间)。
    4. 窗口以外的数据(接收方没空间)。

  • 下面是个滑动后的示意图(收到36的ack,并发出了46-51的字节):


滑动窗口中窗口前段为已发送但为收到ACK的数据,后段为待发送数据。


  • 发送端一次发送多个数据,接收端回传收到的连续数据的ACK信号,缓存缺失数据之后的数据包(保持顺序)。
  • 当发送端收到ACK信号时,窗口向前依次移动,直到遇到有数据未确认时停止。
  • 一段时间后启动超时重传,接收端若收到缺失数据,则和缓存数据一起发送ACK信号,否则,抛弃缓存数据。



2.6 流量控制



接收端在接收到数据后,对其进行处理。


  • 如果发送端的发送速度太快,导致接收端的结束缓冲区很快的填充满了。此时如果发送端仍旧发送数据,那么接下来发送的数据都会丢包,继而导致丢包的一系列连锁反应,如超时重传。


而TCP根据接收端对数据的处理能力,决定发送端的发送速度,这个机制就是流量控制。


简单来说就是接收方处理不过来的时候,就把窗口缩小,并把窗口值告诉发送端。


  • TCP首部有一个字段来通知窗口的大小,接收端通过设置来主动控制传输流量。
  • 如果接收到窗口大小的值为0,那么发送方将停止发送数据,并定期的向接收端发送窗口探测数据段,让接收端把窗口大小告诉发送端。



2.7 拥塞控制



  • 如果网络出现拥塞,分组将会丢失,此时发送方会继续重传,从而导致网络拥塞程度更高。因此当出现拥塞时,应当控制发送方的速率。
    • 这一点和流量控制很像,但是出发点不同。流量控制是为了让接收方能来得及接收,而拥塞控制是为了降低整个网络的拥塞程度
  • 发送方需要维护一个叫做拥塞窗口(cwnd)的状态变量,注意拥塞窗口与发送方窗口的区别:拥塞窗口只是一个状态变量,实际决定发送方能发送多少数据的是发送方窗口

发送端通过拥塞窗口主动控制传输流量。主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。


  • 慢开始:防止双方通信刚开始就传送大量数据包,发送端拥塞窗口初始设置为1MSS(以报文段而非字节为单位),每接受一个ACK信号,窗口扩大为两倍。


    • 发送数据时,取拥塞窗口和滑动窗口的较小值。同时设定一个慢启动阈值,初始值设置为16个报文段,即ssthresh=16。

  • 拥塞避免:


    • 一开始以慢开始算法(指数增长)。当cwnd=16时开始执行拥塞避免算法,呈现线性增长。
    • 当拥塞窗口cwnd=24时出现超时,发送方判定为网络拥塞,于是调整门限值ssthresh=cwnd/2=12,同时设置拥塞窗口为1,进入慢开始阶段。
    • 按照慢开始算法,发送方每收到一个新报文段的确认ACK拥塞窗口值增加。当cwnd=12时(图中点3)执行拥塞避免算法。


TCP以段为单位发送数据包:在建立TCP连接的同时,两端协商发送数据包的单位,称为“最大消息长度”:MSS。


  • 【TCP数据(MSS字节)】【TCP首部(20字节)】【IP首部(20字节)】


  • 快重传和快恢复:
    • 当cwnd=16时(图中点4)出现了一个新的情况,就是发送方连续收到3个对统一报文段的重复确认(3-ACK)。发送方执行快重传和快恢复算法。
      • 在图中点4,发送方知道只是丢失了个别的报文段,于是不启动慢开始,而是先进行快重传然后执行快恢复算法。
      • 发送方设置调整门限值ssthresh=cwnd/2=8, 同时拥塞窗口cwnd=ssthresh=8(点5),然后进行拥塞避免算法。
    • 快重传:收到3个同样的确认就立刻重传特定的报文,不等到超时。
    • 快恢复:cwnd不是从1重新开始。




【部分内容参考自】


  • 《计算机网络–自顶向下方法》
  • 《TCP/IP详解 卷1:协议》
  • TCP的三次握手和四次挥手:https://www.cnblogs.com/xiaokang01/p/10032377.html
  • TCP实现可靠传输:https://www.cnblogs.com/walker993/p/9570902.html
  • TCP协议如何保证可靠传输:https://www.cnblogs.com/xiaokang01/p/10033267.html

推荐阅读
  • Java高并发与多线程(二):线程的实现方式详解
    本文将深入探讨Java中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ... [详细]
  • 本文总结了一些开发中常见的问题及其解决方案,包括特性过滤器的使用、NuGet程序集版本冲突、线程存储、溢出检查、ThreadPool的最大线程数设置、Redis使用中的问题以及Task.Result和Task.GetAwaiter().GetResult()的区别。 ... [详细]
  • MySQL的查询执行流程涉及多个关键组件,包括连接器、查询缓存、分析器和优化器。在服务层,连接器负责建立与客户端的连接,查询缓存用于存储和检索常用查询结果,以提高性能。分析器则解析SQL语句,生成语法树,而优化器负责选择最优的查询执行计划。这一流程确保了MySQL能够高效地处理各种复杂的查询请求。 ... [详细]
  • 本文深入解析了Java 8并发编程中的`AtomicInteger`类,详细探讨了其源码实现和应用场景。`AtomicInteger`通过硬件级别的原子操作,确保了整型变量在多线程环境下的安全性和高效性,避免了传统加锁方式带来的性能开销。文章不仅剖析了`AtomicInteger`的内部机制,还结合实际案例展示了其在并发编程中的优势和使用技巧。 ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • 本文是Java并发编程系列的开篇之作,将详细解析Java 1.5及以上版本中提供的并发工具。文章假设读者已经具备同步和易失性关键字的基本知识,重点介绍信号量机制的内部工作原理及其在实际开发中的应用。 ... [详细]
  • Juval Löwy主张,每个类都应被视为服务,这并非是为了让服务无处不在,而是因为微服务是经过深思熟虑后系统分解的自然结果。在他的设计和构建的系统中,这种理念有助于提高模块化、可维护性和扩展性。通过将每个类视为独立的服务,系统能够更好地应对复杂性,实现更灵活的部署和更高的性能。 ... [详细]
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 性能测试中的关键监控指标与深入分析
    在软件性能测试中,关键监控指标的选取至关重要。主要目的包括:1. 评估系统的当前性能,确保其符合预期的性能标准;2. 发现软件性能瓶颈,定位潜在问题;3. 优化系统性能,提高用户体验。通过综合分析这些指标,可以全面了解系统的运行状态,为后续的性能改进提供科学依据。 ... [详细]
  • B站服务器故障影响豆瓣评分?别担心,阿里巴巴架构师分享预防策略与技术方案
    13日晚上,在视频观看高峰时段,B站出现了服务器故障,引发网友在各大平台上的广泛吐槽。这一事件导致了连锁反应,大量用户纷纷涌入A站、豆瓣和晋江等平台,给这些网站带来了突如其来的流量压力。为了防止类似问题的发生,阿里巴巴架构师分享了一系列预防策略和技术方案,包括负载均衡、弹性伸缩和容灾备份等措施,以确保系统的稳定性和可靠性。 ... [详细]
  • 线程能否先以安全方式获取对象,再进行非安全发布? ... [详细]
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • 本文深入解析了Django框架中的MVT(Model-View-Template)设计模式,详细阐述了其工作原理和应用流程。通过分析URL模式、视图、模型和模板等关键组件,读者将全面理解Django应用程序的架构体系,掌握如何高效地构建和管理Web应用。 ... [详细]
  • 如何利用Java 5 Executor框架高效构建和管理线程池
    Java 5 引入了 Executor 框架,为开发人员提供了一种高效管理和构建线程池的方法。该框架通过将任务提交与任务执行分离,简化了多线程编程的复杂性。利用 Executor 框架,开发人员可以更灵活地控制线程的创建、分配和管理,从而提高服务器端应用的性能和响应能力。此外,该框架还提供了多种线程池实现,如固定线程池、缓存线程池和单线程池,以适应不同的应用场景和需求。 ... [详细]
author-avatar
yun建2502930453
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有